package com.pudding.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.pudding.entity.MyUser;
import com.pudding.entity.StockEntity;
import com.pudding.entity.vo.ExcelVO;
import com.pudding.listener.read.MutliReadListener;
import com.pudding.listener.read.SimpleReadListener;
import com.pudding.listener.read.UserReadListener;
import com.pudding.mapper.ExcelMapper;
import com.pudding.service.ExcelReadService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @Author Pudding
 * @Date 2025/3/19 10:12
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ExcelReadServiceImpl implements ExcelReadService {

    private final ExcelMapper excelMapper;

    @Override
    public void readSimpleExcel(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            // 使用官方提供的分页监听器来读取数据（这里使用的方式是匿名内部类，不建议使用）
            // 这里默认读取行头只能是一行，否则就读取为空
            EasyExcel.read(inputStream, StockEntity.class, new PageReadListener<StockEntity>(dataList -> {
                for (StockEntity stockEntity : dataList) {
                    log.info("读取到一条数据：{}", stockEntity);
                }
            })).sheet().doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void readSimpleExcel2(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            // 使用自定义的监听器来读取数据，默认读取第一页
            // 这里默认读取行头只能是一行，否则就读取为空
            EasyExcel.read(inputStream, StockEntity.class, new SimpleReadListener()).sheet().doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void readMultiSheetExcel(MultipartFile file) {
        // 方式一：读取所有的sheet页
        //try {
        //    EasyExcel.read(file.getInputStream(), StockEntity.class, new SimpleReadListener()).doReadAll();
        //} catch (IOException e) {
        //    throw new RuntimeException(e);
        //}

        // 方式二：读取指定的sheet页
        try (ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build()) {
            // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
            ReadSheet readSheet1 = EasyExcel.readSheet(0).head(StockEntity.class).registerReadListener(new SimpleReadListener()).build();
            ReadSheet readSheet2 = EasyExcel.readSheet(1).head(StockEntity.class).registerReadListener(new SimpleReadListener()).build();
            // 这里注意 一定要把sheet1 sheet2 一起传进去，不然有个问题就是03版的excel 会读取多次，浪费性能
            excelReader.read(readSheet1, readSheet2);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void readMultiHeadExcel(MultipartFile file) {
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet
        try {
            EasyExcel.read(file.getInputStream(), StockEntity.class, new SimpleReadListener()).sheet() //sheet()不填，默认为0，读取第一页
                    // 这里可以设置1，因为头就是一行。如果多行头，可以设置其他值。不传入也可以，因为默认会根据DemoData 来解析，他没有指定头，也就是默认1行
                    .headRowNumber(2).doRead();  //我们这里行头有两个所以设置2
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void readByConverterData(MultipartFile file) {

        //创建自定义监听器
        UserReadListener userReadListener = new UserReadListener();

        //读取第三页的数据
        try {
            EasyExcel.read(file.getInputStream(), MyUser.class, userReadListener).sheet(2).doRead();

            //获取读取到的数据
            List<MyUser> data = userReadListener.getData();
            data.forEach(System.out::println);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用多线程读取excel中百万数据
     *
     * @param file
     */
    @Override
    public void importExcel(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), ExcelVO.class, new MutliReadListener(excelMapper))
                    .sheet()
                    .doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
